import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

import java.io.*;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

public class server {
    private static AtomicInteger concurrentConnections = new AtomicInteger(0);
    private static final String WAV_FILE_PATH = "D:/download/123.wav";
    private static final String SAVE_DIRECTORY = "D:\\recordings\\";

    public static void main(String[] args) throws IOException {
        HttpServer server = HttpServer.create(new InetSocketAddress("localhost", 8222), 0);

        // 处理根路径get请求
        server.createContext("/", new RootHandler());

        // 处理 /other 路径get请求
        server.createContext("/other", new OtherHandler());

        // 处理 /other1 路径post请求
        server.createContext("/other1", new Other1Handler());

        // 处理 /getVoice 路径post请求
        server.createContext("/getVoice", new VoiceRequestHandler());

        // 创建/postWav接口的处理器
        server.createContext("/postWav", new WavUploadHandler());

        // 设置并发连接数
        server.setExecutor(java.util.concurrent.Executors.newFixedThreadPool(10));

        server.start();
        System.out.println("Server started on port 8000.");

        // 定期打印当前并发连接数
        new Thread(() -> {
            while (true) {
                try {
                    Thread.sleep(5000);
                    System.out.println("Current concurrent connections: " + concurrentConnections.get());
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }).start();
    }

    static class WavUploadHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            // 设置CORS头部，允许ESP32跨域访问
            exchange.getResponseHeaders().set("Access-Control-Allow-Origin", "*");
            exchange.getResponseHeaders().set("Access-Control-Allow-Methods", "POST, OPTIONS");
            exchange.getResponseHeaders().set("Access-Control-Allow-Headers", "Content-Type");

            // 处理OPTIONS预检请求
            if ("OPTIONS".equalsIgnoreCase(exchange.getRequestMethod())) {
                exchange.sendResponseHeaders(200, -1);
                return;
            }

            if (!"POST".equalsIgnoreCase(exchange.getRequestMethod())) {
                sendResponse(exchange, 405, "错误: 只支持POST方法");
                return;
            }

            String filename = null;
            FileOutputStream fileOutputStream = null;

            try {
                // 生成随机文件名
                filename = generateRandomFilename();
                Path filePath = Paths.get(SAVE_DIRECTORY, filename);

                // 确保保存目录存在
                Files.createDirectories(Paths.get(SAVE_DIRECTORY));

                fileOutputStream = new FileOutputStream(filePath.toFile());
                InputStream requestBody = exchange.getRequestBody();

                byte[] buffer = new byte[8192];
                int bytesRead;
                long totalBytes = 0;

                System.out.println("开始接收WAV文件: " + filename);

                while ((bytesRead = requestBody.read(buffer)) != -1) {
                    fileOutputStream.write(buffer, 0, bytesRead);
                    totalBytes += bytesRead;

                    // 每写入64KB打印一次进度
                    if (totalBytes % (64 * 1024) == 0) {
                        System.out.printf("文件 %s 已接收: %.2f KB\n",
                                filename, totalBytes / 1024.0);
                    }
                }

                fileOutputStream.flush();

                System.out.printf("WAV文件保存成功: %s, 大小: %.2f KB\n",
                        filename, totalBytes / 1024.0);

                // 验证WAV文件
                if (isValidWavFile(filePath)) {
                    String response = String.format("WAV文件上传成功!\n文件名: %s\n文件大小: %.2f KB\n保存路径: %s",
                            filename, totalBytes / 1024.0,
                            filePath.toString());
                    sendResponse(exchange, 200, response);

                    // 打印文件信息
                    printWavFileInfo(filePath);
                } else {
                    Files.deleteIfExists(filePath);
                    sendResponse(exchange, 400, "错误: 上传的文件不是有效的WAV格式");
                }

            } catch (Exception e) {
                System.err.println("处理请求时发生错误: " + e.getMessage());
                e.printStackTrace();

                if (filename != null) {
                    try {
                        Files.deleteIfExists(Paths.get(SAVE_DIRECTORY, filename));
                    } catch (IOException deleteEx) {
                        System.err.println("删除不完整文件失败: " + deleteEx.getMessage());
                    }
                }

                sendResponse(exchange, 500, "服务器错误: " + e.getMessage());
            } finally {
                if (fileOutputStream != null) {
                    try {
                        fileOutputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

    }

    static class RootHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            concurrentConnections.incrementAndGet();

            if ("GET".equals(exchange.getRequestMethod())) {
                String response = "Hello from root path!";
                exchange.sendResponseHeaders(200, response.length());
                OutputStream os = exchange.getResponseBody();
                os.write(response.getBytes());
                os.close();
                // 监控连接释放事件
                System.out.println("root Connection released");
            }

            concurrentConnections.decrementAndGet();
        }
    }

    static class OtherHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            concurrentConnections.incrementAndGet();

            if ("GET".equals(exchange.getRequestMethod())) {
                String response = "This is a response for /other path.";
                exchange.sendResponseHeaders(200, response.length());
                OutputStream os = exchange.getResponseBody();
                os.write(response.getBytes());
                os.close();
            }
            // 监控连接释放事件
            System.out.println("/other Connection released");
            concurrentConnections.decrementAndGet();
        }
    }

    static class Other1Handler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            concurrentConnections.incrementAndGet();

            if ("POST".equals(exchange.getRequestMethod())) {
                String response = "This is a response for /other1 post path.";
                exchange.sendResponseHeaders(200, response.length());
                OutputStream os = exchange.getResponseBody();
                os.write(response.getBytes());
                os.close();
            }
            // 监控连接释放事件
            System.out.println("/other Connection released");
            concurrentConnections.decrementAndGet();
        }
    }

    /**
     * 自定义处理器，处理/getVoice请求
     */
    static class VoiceRequestHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) {
            try {
                // 校验请求方法：仅允许GET请求
                if (!"GET".equals(exchange.getRequestMethod())) {
                    sendErrorResponse(exchange, 405, "仅支持GET请求");
                    return;
                }

                // 加载本地WAV文件
                File wavFile = new File(WAV_FILE_PATH);
                // 校验文件是否存在
                if (!wavFile.exists()) {
                    sendErrorResponse(exchange, 404, "文件不存在：" + WAV_FILE_PATH);
                    return;
                }
                // 校验文件是否为普通文件（非目录）
                if (!wavFile.isFile()) {
                    sendErrorResponse(exchange, 400, "路径不是有效文件：" + WAV_FILE_PATH);
                    return;
                }

                // 4. 设置响应头：指定文件类型为WAV音频，返回文件长度
                exchange.getResponseHeaders().set("Content-Type", "audio/wav");
                exchange.getResponseHeaders().set("Content-Length", String.valueOf(wavFile.length()));
                // 允许跨域请求（可选，前端调用时需要）
                exchange.getResponseHeaders().set("Access-Control-Allow-Origin", "*");

                // 5. 发送响应状态码（200表示成功），并打开响应输出流
                exchange.sendResponseHeaders(200, wavFile.length());

                // 6. 读取WAV文件并写入响应流
                try (FileInputStream fis = new FileInputStream(wavFile);
                     OutputStream os = exchange.getResponseBody()) {
                    byte[] buffer = new byte[4096]; // 4KB缓冲区，提升读写效率
                    int bytesRead;
                    while ((bytesRead = fis.read(buffer)) != -1) {
                        os.write(buffer, 0, bytesRead);
                    }
                    os.flush();
                    System.out.println("文件发送成功：" + wavFile.getName() + "，大小：" + wavFile.length() + "字节");
                }

            } catch (Exception e) {
                // 捕获异常并返回500错误
                try {
                    sendErrorResponse(exchange, 500, "服务器内部错误：" + e.getMessage());
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                e.printStackTrace();
            } finally {
                // 关闭请求交换，释放资源
                exchange.close();
            }
        }
    }

    /**
     * 发送错误响应
     *
     * @param exchange 请求交换对象
     * @param code     状态码
     * @param message  错误信息
     */
    private static void sendErrorResponse(HttpExchange exchange, int code, String message) throws Exception {
        byte[] errorBytes = message.getBytes(StandardCharsets.UTF_8);
        exchange.getResponseHeaders().set("Content-Type", "text/plain; charset=UTF-8");
        exchange.sendResponseHeaders(code, errorBytes.length);
        try (OutputStream os = exchange.getResponseBody()) {
            os.write(errorBytes);
        }
        System.out.println("请求失败：" + code + "，原因：" + message);
    }


    private static String generateRandomFilename() {
        long timestamp = System.currentTimeMillis();
        int randomNum = new Random().nextInt(10000);
        return "esp32_" + timestamp + "_" + randomNum + ".wav";
    }

    private static boolean isValidWavFile(Path filePath) {
        try (FileInputStream fis = new FileInputStream(filePath.toFile())) {
            byte[] header = new byte[12];
            if (fis.read(header) != 12) {
                return false;
            }

            // 检查RIFF头
            if (header[0] != 'R' || header[1] != 'I' ||
                    header[2] != 'F' || header[3] != 'F') {
                return false;
            }

            // 检查WAVE格式
            byte[] waveHeader = new byte[4];
            if (fis.read(waveHeader) != 4) {
                return false;
            }
            if (waveHeader[0] != 'W' || waveHeader[1] != 'A' ||
                    waveHeader[2] != 'V' || waveHeader[3] != 'E') {
                return false;
            }

            return true;
        } catch (IOException e) {
            return false;
        }
    }

    private static void printWavFileInfo(Path filePath) {
        try (RandomAccessFile raf = new RandomAccessFile(filePath.toFile(), "r")) {
            byte[] header = new byte[44];
            raf.read(header);

            // 读取WAV文件信息
            int channels = (header[23] << 8) | header[22];
            int sampleRate = (header[27] << 24) | (header[26] << 16) | (header[25] << 8) | header[24];
            int bitsPerSample = (header[35] << 8) | header[34];
            int dataSize = (header[43] << 24) | (header[42] << 16) | (header[41] << 8) | header[40];

            System.out.println("=== WAV文件信息 ===");
            System.out.println("文件名: " + filePath.getFileName());
            System.out.println("声道数: " + channels);
            System.out.println("采样率: " + sampleRate + " Hz");
            System.out.println("位深度: " + bitsPerSample + " bit");
            System.out.println("数据大小: " + dataSize + " 字节");
            System.out.println("持续时间: " + (dataSize / (sampleRate * channels * bitsPerSample / 8.0)) + " 秒");
            System.out.println("==================");

        } catch (IOException e) {
            System.err.println("读取WAV文件信息失败: " + e.getMessage());
        }
    }

    private static void sendResponse(HttpExchange exchange, int statusCode, String response) throws IOException {
        exchange.getResponseHeaders().set("Content-Type", "text/plain; charset=UTF-8");
        byte[] responseBytes = response.getBytes("UTF-8");
        exchange.sendResponseHeaders(statusCode, responseBytes.length);

        try (OutputStream os = exchange.getResponseBody()) {
            os.write(responseBytes);
        }
    }
}
